home *** CD-ROM | disk | FTP | other *** search
- /**
- File: Mode.c
-
- Contents: Creates a picture consisting of multi colored rectangles and rotates a
- text shape over the top of the picture. Menus allow the user to try
- different transfer modes, colors, and update schemes.
-
- The following filles are required to build this app:
-
- mode.c, ColorLibrary.c, FontLibrary.c, GraphicsDebugLibrary.c,
- GraphicsLibrary.c, OffscreenLibrary.c, PictureLibrary.c, QDLibrary.c,
- ShapeLibrary.c, TextLibrary.c, TransferModeLibrary.c, TransformLibrary.c.
-
- Change History:
-
- 4/96 bob Updated #includes to support changed GX Library names.
- Changed fixed to Fixed.
- Updated the note regarding the files needed to run.
- Updated the copyright date.
-
- ©1991 - 1996 Apple Computer Inc. All Rights reserved
- **/
-
-
- #include <Desk.h>
- #include <Events.h>
- #include <Fonts.h>
- #include <Menus.h>
- #include <Memory.h>
- #include <ToolUtils.h>
- #include <Windows.h>
-
- #include "GraphicsLibraries.h"
- #include <GXErrors.h>
- #include <GXEnvironment.h>
- #include "FontLibrary.h"
- #include "OffscreenLibrary.h"
- #include "QDLibrary.h"
-
- #include "mode.h"
-
- /*______________________________________________________________________________________*/
- /* Non-Shell Global Variables */
-
- Boolean randColor, randXfer, updateDiff, macUpdate, useClip, eraseScreen;
- char curXfer;
- commonColor curColor;
- static char lastXfer;
-
-
- /*______________________________________________________________________________________*/
- /* Non-Shell Prototypes */
- void MakeTest(WindowPtr win);
- void KillTest(WindowPtr win);
- void MouseClickTest(WindowPtr win);
- void KeyTest(WindowPtr win);
- void IdleTest(WindowPtr win);
- void UpdateTest(WindowPtr win);
-
-
- /*______________________________________________________________________________________*/
- /* Shell Global Variables */
-
- /* Default window vars: */
- Str255 gWindowTitle = "\p Mode test ??";
- Rect gWindowRect = { 42,4,476,636 };
-
- Boolean gOuttaHere = false; /* Event loop cycles until this is TRUE */
- short gOptionOn = false; /* Is the option key being pressed? */
- short gCmdOn = false; /* Is the command key being pressed? */
- Boolean gWNEAvailable; /* Specifies if WaitNextEvent is available */
- WindowPtr gAppWindow;
- gxPoint gLastPt;
-
-
- /*______________________________________________________________________________________*/
- void InitMac(void);
- void InitMac()
- {
- EventRecord theEvent;
-
- GXEnterGraphics();
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitCursor();
-
- gWNEAvailable = true;
-
- EventAvail(everyEvent,&theEvent); /* Force windows to front… (for MF) */
- }
-
-
- /*______________________________________________________________________________________*/
- WindowPtr CreateWindow(Str255, Rect *);
-
- /* CreateWindow takes a rect specification as well as a title string as parameters. The
- // window is created with the specified title at the desired size. NOTE: if a nil rectangle
- // is passed the window is created the size of the startup monitor inset 20 pixels.
- */
-
- WindowPtr CreateWindow(Str255 windowTitle, Rect *r)
- {
- WindowPtr theWindow;
- Rect theRect;
-
- if (r == nil) {
- theRect.top = qd.screenBits.bounds.top + 50;
- theRect.left = qd.screenBits.bounds.left + 20;
- theRect.bottom = qd.screenBits.bounds.bottom - 20;
- theRect.right = qd.screenBits.bounds.right - 20;
- }
- else
- theRect = *r;
-
- theWindow = NewWindow(nil, &theRect, windowTitle, true, documentProc, (WindowPtr) -1L, false, 0L);
-
- GXIgnoreGraphicsNotice(transform_already_set);
- SetDefaultViewPort(GXNewWindowViewPort(theWindow));
- GXPopGraphicsNotice();
-
- SetPort(theWindow);
-
- return theWindow;
- }
-
-
- /*______________________________________________________________________________________*/
- void InitAppMenus(void);
- void InitAppMenus()
- {
- short i;
-
- /* Insert all app menus into the menu bar */
- for (i = 0; i < mcMenuCount; i++)
- InsertMenu(GetMenu(mcFirstMenuID +i), AT_END);
-
- /* Insert all heirarchical menus into the menu bar */
- for (i = 0; i < mcHeirCount; i++)
- InsertMenu(GetMenu(mcFirstHeirID +i), AT_END);
-
- /* Add the DRVRs to the Apple Menu */
- AddResMenu(GetMHandle(mcAppleMenuID),'DRVR');
- }
-
- /*______________________________________________________________________________________*/
- void AdjustMenus(void);
- void AdjustMenus()
- {
- }
-
-
- /*______________________________________________________________________________________*/
- void DoGrowWindow(WindowPtr, EventRecord *);
- void DoGrowWindow(WindowPtr theWindow, EventRecord *theEvent)
- {
- long newSize;
- if (theWindow != FrontWindow())
- SelectWindow(theWindow);
- else
- SetPort(theWindow);
-
- newSize = GrowWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
- if (newSize != 0)
- SizeWindow(theWindow, LoWord(newSize), HiWord(newSize), true);
-
- }
-
-
- /*______________________________________________________________________________________*/
- void DoMenuCommand(long);
- void DoMenuCommand(long menuData)
- {
- short theMenu;
- short theItem;
- Str255 theName;
- short theRefNum;
-
- static char diffStr[] = "\pUse DiffShape";
- static char pictureStr[] = "\pUse Offscreen Background";
-
- Boolean imageChanged = true;
- OSErr result = noErr;
-
-
- theMenu = HiWord(menuData);
- theItem = LoWord(menuData);
-
- switch (theMenu) {
- case mcAppleMenuID:
- switch (theItem) {
- case mcAbout: break;
- default:
- GetItem(GetMHandle(mcAppleMenuID), theItem, theName);
- theRefNum = OpenDeskAcc(theName);
- break;
- }
- break;
-
- case mcFileMenuID:
- switch ( theItem ) {
- case mcNew: break;
- case mcOpen: break;
- case mcClose: break;
- case mcSave: break;
- case mcSaveAs: break;
- case mcPageSetUp: break;
- case mcPrint: break;
- case mcQuit: gOuttaHere = true; break;
- }
- break;
-
- case mcColorMenuID:
- switch ( theItem ) {
- case ColorSpaceBarChanges:
- CheckItem(GetMHandle(mcColorMenuID), ColorSpaceBarChanges, true);
- CheckItem(GetMHandle(mcColorMenuID), ColorRandom, false);
- randColor = false;
- break;
- case ColorRandom:
- CheckItem(GetMHandle(mcColorMenuID), ColorSpaceBarChanges, false);
- CheckItem(GetMHandle(mcColorMenuID), ColorRandom, true);
- randColor = true;
- break;
- }
- break;
-
- case mcXferMenuID:
- switch ( theItem ) {
- case gxCopyMode:
- case gxAddMode:
- case gxBlendMode:
- case gxMigrateMode:
- case gxMinimumMode:
- case gxMaximumMode:
- case gxHighlightMode:
- case gxAndMode:
- case gxOrMode:
- case gxXorMode:
- //LS case pixelXorMode:
- case gxRampAndMode:
- case gxRampOrMode:
- case gxRampXorMode:
- case gxOverMode:
- case gxAtopMode:
- case gxExcludeMode:
- case gxFadeMode:
- CheckItem(GetMHandle(mcXferMenuID), curXfer, false);
- CheckItem(GetMHandle(mcXferMenuID), XferRandom, false);
- CheckItem(GetMHandle(mcXferMenuID), theItem, true);
- curXfer = theItem;
- randXfer = false;
- break;
- case XferRandom:
- CheckItem(GetMHandle(mcXferMenuID), XferRandom, true);
- CheckItem(GetMHandle(mcXferMenuID), curXfer, false);
- randXfer = true;
- break;
- }
- break;
-
- case mcUpdateMenuID:
- switch ( theItem ) {
- case UpdatesUseDiffShape:
- updateDiff = (updateDiff) ? false : true;
- SetItem(GetMHandle(mcUpdateMenuID), UpdatesUseDiffShape, (ConstStr255Param)(updateDiff ? pictureStr : diffStr));
- eraseScreen = true;
- break;
- case UpdatesMacStyleUpdates:
- macUpdate = (macUpdate) ? false : true;
- CheckItem(GetMHandle(mcUpdateMenuID), UpdatesMacStyleUpdates, macUpdate);
- break;
- case UpdatesClipToTextBox:
- useClip = (useClip) ? false : true;
- CheckItem(GetMHandle(mcUpdateMenuID), UpdatesClipToTextBox, useClip);
- eraseScreen = true;
- break;
- }
- break;
- }
-
- HiliteMenu(0);
- }
-
-
- /*______________________________________________________________________________________*/
- void DoMouseDown(EventRecord *);
- void DoMouseDown(EventRecord *theEvent)
- {
- short thePart;
- WindowPtr theWindow;
- register i;
-
-
- thePart = FindWindow(theEvent->where, &theWindow);
- switch ( thePart ) {
- case inMenuBar:
- AdjustMenus();
- DoMenuCommand(MenuSelect(theEvent->where));
- break;
-
- case inSysWindow:
- SystemClick( theEvent, theWindow );
- break;
-
- case inContent:
- {
- Point QDpt;
- gxPoint pt;
-
-
- GetMouse(&QDpt);
-
- pt.x = ff(QDpt.h);
- pt.y = ff(QDpt.v);
- MouseClickTest(theWindow);
- }
-
- break;
-
- case inDrag:
- DragWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
- break;
-
- case inGrow:
- DoGrowWindow(theWindow, theEvent);
- break;
-
- case inZoomIn:
- case inZoomOut:
- if ( TrackBox(theWindow, theEvent->where, thePart) )
- {
- SetPort(theWindow);
- ZoomWindow(theWindow, thePart, true);
- InvalRect(&theWindow->portRect);
- }
- break;
- }
- }
-
-
- /*______________________________________________________________________________________*/
- void DoKeyDown(EventRecord *);
- void DoKeyDown(EventRecord *theEvent)
- {
- char theKey;
-
- gCmdOn = (theEvent->modifiers & cmdKey);
- theKey = theEvent->message & charCodeMask;
-
- if ((gCmdOn) && (theEvent->what == keyDown)) {
- AdjustMenus();
- DoMenuCommand(MenuKey(theKey));
- }
- KeyTest(gAppWindow);
- }
-
-
- /*______________________________________________________________________________________*/
- void DoEvent(EventRecord *);
- void DoEvent(EventRecord *theEvent)
- {
- switch (theEvent->what) {
- case nullEvent:
- IdleTest(gAppWindow);
- break;
-
- case mouseDown:
- DoMouseDown(theEvent);
- break;
-
- case keyDown:
- case autoKey:
- DoKeyDown(theEvent);
- break;
-
- case activateEvt:
- case updateEvt:
- BeginUpdate(gAppWindow);
- UpdateTest(gAppWindow);
- EndUpdate(gAppWindow);
- break;
-
- case diskEvt:
- break;
- }
- }
-
- /*______________________________________________________________________________________*/
- void MainLoop(void);
- void MainLoop()
- {
- EventRecord theEvent;
-
- do {
- if (gWNEAvailable)
- WaitNextEvent(everyEvent, &theEvent, 0, nil);
- else {
- SystemTask();
- GetNextEvent(everyEvent, &theEvent);
- }
-
- DoEvent(&theEvent);
-
- } while (! gOuttaHere);
- }
-
- /*______________________________________________________________________________________*/
- void main(void);
- void main()
- {
- MaxApplZone();
- MoreMasters(); MoreMasters(); MoreMasters();
- MoreMasters(); MoreMasters(); MoreMasters();
-
- InitMac(); /* Call desired initialization procedures. */
-
- InitAppMenus(); /* init and draw menu */
- DrawMenuBar();
-
- gAppWindow = CreateWindow(gWindowTitle, &gWindowRect); /* Create the application window. */
-
- MakeTest(gAppWindow);
-
- gLastPt.x = gLastPt.y = ff(-1000);
-
- MainLoop();
-
- KillTest(gAppWindow);
- DisposeWindow(gAppWindow); /* Create the application window. */
-
- GXExitGraphics();
- }
-
-
- /*______________________________________________________________________________________*/
-
- void setPictureXform(gxShape aPicture, gxTransform aTransform);
- gxShape makeATextShape(char *sometext, Fixed x, Fixed y, Fixed thesize);
- void undrawUsingDiff(void);
- void undrawUsingOffscreen(void);
- void invalShape(gxShape aShape);
- short xrand(long max);
- void xsrand(unsigned n);
-
- gxShape shPicture = nil, shText = nil, shTextBox = nil;
- gxShape shPictureBox = nil, shMap = nil;
- offscreen canvas;
-
- /*______________________________________________________________________________________
- set it all up,
- ______________________________________________________________________________________*/
- void MakeTest(WindowPtr win)
- {
- register long gxColorIndex;
- register short x, y;
- gxShape grunt;
- gxRectangle bounds;
- gxRectangle r;
- gxBitmap bmap;
-
- randColor = randXfer = false;
- updateDiff = true;
- macUpdate = useClip = false;
- curColor = violet;
- curXfer = gxRampXorMode;
- lastXfer = gxCopyMode;
-
- InitCommonColors(); /* to use the common colors library */
- xsrand(38); /* init the random seed */
-
- /* make a picture with repeating squares of different colors, by creating a picture shape */
- /* and then adding a bunch of shapes to it. */
-
- shPicture = GXNewShape(gxPictureType);
- GXSetShapeFill(shPicture, gxOpenFrameFill);
- for (y=100, gxColorIndex = cyan; y <= 300; y += 50) {
- for (x=150; x <= 350; x += 50, gxColorIndex += 4) {
- grunt = NewShape4(gxRectangleType, ff(x), ff(y), ff(x + 50), ff(y + 50));
- SetShapeCommonColor(grunt, gxColorIndex);
- AddToShape(shPicture, grunt);
- GXDisposeShape(grunt);
- }
- }
-
- /* make a text shape. set it up so that its gxTransform will be rotated and not the shape. */
- shText = makeATextShape("Mødé Test", ff(75), ff(250), ff(96));
- GXSetShapeAttributes(shText, gxMapTransformShape);
- SetShapeCommonColor(shText, curColor);
-
- /*
- // for onscreen updating:
- //
- // now make two gxRectangle shapes, each one having a gxRectangle corresponding to one of the
- // two previous shapes we created. these will be used to find the area of the text that
- // is not over the picture (over the white background) so that this area can be drawn in
- // white to "erase" the text before rotating and redrawing the text.
- */
-
- GXGetShapeBounds(shText, 0, &bounds);
- shTextBox = GXNewRectangle(&bounds);
- GXSetShapePen(shTextBox, ff(1));
- GXGetShapeBounds(shPicture, 0, &bounds);
- shPictureBox = GXNewRectangle(&bounds);
- GXSetShapePen(shPictureBox, ff(1));
-
- /*
- // for offscreen updating:
- //
- // create a gxBitmap shape that is the size of the screen and as deep as the deepest
- // monitor in our coordinate space. the offscreen library copies our gxBitmap
- // so we can dispose the one we created once the offscreen has been created.
- // note: setting the map.image to nil will tell graphics to allocate the storage for the
- // bits in it's gxHeap. because we are not guaranteed that the gxHeap will be where we
- // can modify it (it could be on an accelerator, for instance) we cannot get at the
- // image with GXGetBitmap(). if we want to have the image to modify we should allocate
- // our own image.
- */
- {
- gxBitmap map;
- gxPoint pt = { 0, 0 };
- Rect bigRect = { -32767, -32767, 32767, 32767 };
- GDHandle gd = GetMaxDevice(&bigRect);
- gxShape shErase;
- gxTransform savedXform;
-
- map.width = (long)(win->portRect.right - win->portRect.left);
- map.height = (long)(win->portRect.bottom - win->portRect.top);
- map.pixelSize = (**(**gd).gdPMap).pixelSize;
- map.rowBytes = 0L;
- map.image = nil;
- map.space = gxIndexedSpace;
- map.profile = nil;
- map.set = GXCloneColorSet(commonColorSet);
-
- shMap = GXNewBitmap(&map, &pt);
- CreateOffscreen(&canvas, shMap);
-
- /* white out all bits in the offscreen */
- GXGetShapeBounds(shMap, 1, &bounds);
- shErase = GXNewRectangle(&bounds);
- SetShapeCommonColor(shErase, gxWhite);
- GXSetShapeTransform(shErase, canvas.xform);
- GXDrawShape(shErase);
- DisposeShapeAt(&shErase);
- DisposeShapeAt(&shMap);
-
- /*
- // set the gxTransform of our picture to the gxTransform of the offscreen
- // which has its own gxViewPort. any drawing of the picture shape will
- // happen in the offscreen's gxViewPort, which has our bit shape as its gxBitmap.
- // since our application allows us to switch between drawing the offscreen to
- // the screen, and actually drawing the picture, we need to set the picture's
- // gxTransform back so that we can draw it on the screen if we want to.
- */
-
- savedXform = GXGetShapeTransform(shPicture);
- setPictureXform(shPicture, canvas.xform);
- GXDrawShape(shPicture);
- setPictureXform(shPicture, savedXform);
- }
- }
-
-
- void UpdateTest(WindowPtr win)
- {
- if (updateDiff)
- GXDrawShape(shPicture); /* draw the picture directly to the screen */
- else
- GXDrawShape(canvas.draw); /* draw the offscreen to the screen */
- GXDrawShape(shText);
- }
-
-
- /*______________________________________________________________________________________*/
- void IdleTest(WindowPtr win)
- {
- if (randXfer) { /* flag tells us to change the transfer mode randomly */
- curXfer = (char)xrand(gxFadeMode);
- SetShapeCommonTransfer(shText, curXfer);
- }
- else if (lastXfer != curXfer) { /* flag tells us to change the transfer mode */
- lastXfer = curXfer;
- SetShapeCommonTransfer(shText, curXfer);
- }
-
- if (randColor) { /* flag tells us to change the common gxColor randomly */
- curColor = (long)xrand(violet);
- SetShapeCommonColor(shText, curColor);
- }
-
- if (eraseScreen) { /* for cleaning up when user changes options */
- EraseRect(&win->portRect);
- UpdateTest(win);
- eraseScreen = false;
- }
- else if (macUpdate) { /* erase, invalidate & let the mac update mechanism draw it */
- GrafPtr savedPort;
-
- GetPort(&savedPort);
- SetPort(win);
- if (updateDiff) /* use diffshape to erase */
- undrawUsingDiff();
- else
- undrawUsingOffscreen(); /* draw undrawUsingOffscreen to erase */
- SetPort(savedPort);
-
- RotateShapeAboutCenter(shText, ff(15));
- invalShape(shTextBox);
- RotateShapeAboutCenter(shTextBox, ff(15));
- invalShape(shTextBox);
- }
- else {
- if (updateDiff) /* use diffshape to erase */
- undrawUsingDiff();
- else
- undrawUsingOffscreen(); /* use undrawUsingOffscreen to erase */
-
- RotateShapeAboutCenter(shText, ff(15));
- GXDrawShape(shText);
- RotateShapeAboutCenter(shTextBox, ff(15));
- }
- }
-
-
- /*______________________________________________________________________________________
- make a copy of the text box, which is always rotated to the same angle as the text.
- diff it with the picture recatngle, and then draw it (its gxColor is already set to
- white). then draw the picture to "erase" the text over it, rotate the text and
- draw the text, and rotate the text box shape to keep it in synch with the text shape.
- ______________________________________________________________________________________*/
- void undrawUsingDiff(void)
- {
- gxRectangle bounds;
- gxShape shSaveClip;
- gxShape shFoo = CopyShape(shTextBox);
-
- GXDifferenceShape(shFoo, shPictureBox);
- SetShapeCommonColor(shFoo, gxWhite);
-
- if (useClip) {
- shSaveClip = GXGetShapeClip(shPictureBox);
- GXSetShapeClip(shPicture, shTextBox);
- }
- GXDrawShape(shFoo);
- GXDrawShape(shPicture);
- if (useClip) {
- GXSetShapeClip(shPicture, shSaveClip);
- DisposeShapeAt(&shSaveClip);
- }
- GXDisposeShape(shFoo);
- }
-
-
- /*______________________________________________________________________________________
- draw the offscreen with or without a clip.
- ______________________________________________________________________________________*/
- void undrawUsingOffscreen(void)
- {
- gxShape shSaveClip;
-
- if (useClip) {
- shSaveClip = GXGetShapeClip(canvas.draw);
- GXSetShapeClip(canvas.draw, shTextBox);
- }
- GXDrawShape(canvas.draw);
- if (useClip) {
- GXSetShapeClip(canvas.draw, shSaveClip); /* restore offscreen's clip */
- DisposeShapeAt(&shSaveClip);
- }
- }
-
-
- /*______________________________________________________________________________________*/
- void MouseClickTest(WindowPtr win)
- {
- while(Button());
- }
-
-
- /*______________________________________________________________________________________*/
- void KeyTest(WindowPtr win)
- {
- curColor += 1;
- if (curColor > apple_blue)
- curColor = gxBlack;
- SetShapeCommonColor(shText, curColor);
- }
-
-
- /*______________________________________________________________________________________*/
- void KillTest(WindowPtr win)
- {
- DisposeOffscreen(&canvas);
- DisposeShapeAt(&shPicture);
- DisposeShapeAt(&shText);
- DisposeShapeAt(&shTextBox);
- DisposeShapeAt(&shPictureBox);
- DisposeShapeAt(&shMap);
- DisposeCommonColors();
- }
-
-
- /*______________________________________________________________________________________
- pretty simple - a smarter version would check the shapeType and recursively
- traverse sub-pictures.
- ______________________________________________________________________________________*/
- void setPictureXform(gxShape aPicture, gxTransform aTransform)
- {
- register long i;
-
- GXSetShapeTransform(aPicture, aTransform);
- for (i=GXGetPicture(aPicture, nil, nil, nil, nil); i != 0; i--) {
- GXSetShapeTransform(GetPictureItem(aPicture, i, nil, nil, nil, nil), aTransform);
- }
- }
-
- /*______________________________________________________________________________________
- create a qd region that spans all the points on the shape and invalidate that region.
- ______________________________________________________________________________________*/
- void invalShape(gxShape aShape)
- {
- register long i, last, numberOfPointsInShape;
- gxPoint pt, fixedStartPt;
- Point qdStartPt, qdPt;
- RgnHandle aRgn = NewRgn();
-
- numberOfPointsInShape = GXCountShapePoints(aShape, 1L);
-
- GetShapeIndexPoint(aShape, 1, &fixedStartPt);
-
- FixedPointToShort(&fixedStartPt, &qdStartPt);
-
- OpenRgn();
- MoveTo(qdStartPt.h, qdStartPt.v);
- for (i = 2; i <= numberOfPointsInShape; i++) {
- GetShapeIndexPoint(aShape, i, &pt);
-
- FixedPointToShort(&pt, &qdPt);
- LineTo(qdPt.h, qdPt.v);
- }
- LineTo(qdStartPt.h, qdStartPt.v);
- CloseRgn(aRgn);
-
- InvalRgn(aRgn);
- DisposeRgn(aRgn);
- }
-
-
- /*______________________________________________________________________________________*/
- gxShape makeATextShape(char *sometext, Fixed x, Fixed y, Fixed thesize)
- {
- gxPoint where;
- gxShape thetext;
-
- where.x = x;
- where.y = y;
- thetext = NewCString(sometext,&where);
-
- GXSetShapeTextSize(thetext,thesize);
- SetShapeCommonFont(thetext, timesFont);
- return(thetext);
- }
-
-
- /* ripped from the ansi library */
-
- static unsigned long seed = 1;
-
- short xrand(long max)
- {
- short foo;
-
- seed = seed * 1103515245 + 12345;
- asm {
- move.w seed,d0 ; high word of long
- andi.w #0x7FFF,d0 ; remove high bit
- move.w d0,foo ; needs futher processing
- }
- while(foo > max) /* not very clever (or correct), but it was fast and easy */
- foo = foo >> 1;
- return(foo);
- }
-
-
- void xsrand(unsigned n)
- {
- seed = n;
- }